#include "Thread.hpp"
#include <vector>
#include <queue>
#include "Log.hpp"

using namespace ThreadMoudle;

static const int default_num = 5;

template <class T>
class ThreadPool
{
private:
    void LockQueue()
    {
        pthread_mutex_lock(&_mutex);
    }
    void UnlockQueue()
    {
        pthread_mutex_unlock(&_mutex);
    }
    void Sleep()
    {
        pthread_cond_wait(&_cond, &_mutex);
    }
    void WakeUp()
    {
        pthread_cond_signal(&_cond);
    }
    void WakeUpAll()
    {
        pthread_cond_broadcast(&_cond);
    }

    bool IsEmpty()
    {
        return _task_queue.empty();
    }

    void HandleTask(const std::string &name)
    {
        while (true)
        {
            LockQueue();
            if (IsEmpty() && _is_running)
            {
                _sleep_num++;
                LOG(INFO, "%s thread sleep begin!\n", name.c_str());
                Sleep();
                LOG(INFO, "%s thread wakeup!\n", name.c_str());
                _sleep_num--;
            }
            if (IsEmpty() && !_is_running)
            {
                UnlockQueue();
                // std::cout << name << " quit" << std::endl;
                LOG(INFO, "%s thread quit\n", name.c_str());
                break;
            }

            // 取任务
            T task = _task_queue.front();
            _task_queue.pop();
            UnlockQueue();

            // 处理任务
            task();
            // std::cout << name << "  :" << task.result() << std::endl;
            LOG(DEBUG, "hander task done, task is : %s\n", task.result().c_str());
        }
    }
    ThreadPool(int num = default_num)
        : _thread_num(num), _sleep_num(0)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);
    }

    ThreadPool(int num = default_num)
        : _thread_num(num), _sleep_num(0)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);
    }

    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
    }

    void Init()
    {
        func_t func = std::bind(&ThreadPool::HandleTask, this, std::placeholders::_1);

        for (int i = 0; i < _thread_num; ++i)
        {
            std::string name = "thread-" + std::to_string(i + 1);
            _threads.emplace_back(name, func);
            LOG(DEBUG, "construct thread %s done, init success\n", name.c_str());
        }
    }

    void operator=(const Thread<T>& ) = delete;

    ThreadPool<const ThreadPool<T>& > = delete;
public:

    static ThreadPool<T>* GetInstance()
    {
        if(tp == nullptr)
        {   
            LOG(INFO,"creat threadpool\n");
            tp = new ThreadPool();
            tp->Init();
            tp->Start();

        }
        else{
            LOG(INFO,"get threadpool\n");
        }
        return tp;
    }

    void Start()
    {
        _is_running = true;
        for (auto &thread : _threads)
        {
            LOG(DEBUG, "start thread %s done.\n", thread.Name().c_str());
            thread.Start();
        }
    }

    void Stop()
    {
        if (_is_running)
        {
            LockQueue();
            _is_running = false;
            WakeUpAll();
            UnlockQueue();
            LOG(INFO, "Thread Pool Stop Success!\n");
        }
    }

    void Equeue(const T &task)
    {
        LockQueue();
        _task_queue.push(task);
        if (_sleep_num > 0)
            WakeUp();
        UnlockQueue();
    }

private:
    std::vector<Thread> _threads;
    std::queue<T> _task_queue;

    int _thread_num;
    bool _is_running;
    int _sleep_num;
    pthread_mutex_t _mutex;
    pthread_cond_t _cond;

    static ThreadPool<T> *tp;
};

template<class T>
ThreadPool<T>* ThreadPool<T>::tp = nullptr;


// #include "Thread.hpp"
// #include <vector>
// #include <queue>
// #include <unistd.h>
// using namespace ThreadMoudle;

// static const int default_thread_num = 5;

// template <class T>
// class ThreadPool
// {
// public:
//     // 加锁
//     void LockQueue()
//     {
//         pthread_mutex_lock(&_mutex);
//     }
//     // 解锁
//     void UnlockQueue()
//     {
//         pthread_mutex_unlock(&_mutex);
//     }
//     // 判断是够为空
//     bool IsEmpty()
//     {
//         return _task_queue.size() == 0;
//     }
//     // 等待
//     void Sleep()
//     {
//         pthread_cond_wait(&_cond,&_mutex);
//     }
//     // 唤醒
//     void Wakeup()
//     {
//         pthread_cond_signal(&_cond);
//     }
//     // 全部唤醒
//     void WakeUpAll()
//     {
//         pthread_cond_broadcast(&_cond);
//     }

//     // 生产
//     void Equeue(T task)
//     {
//         LockQueue();

//         if (_is_running)
//         {
//             _task_queue.push(task);
//             if (_sleep_num > 0)
//                 Wakeup();
//         }
//         UnlockQueue();
//     }

//     // 消费
//     void HandleTask(const std::string &name)
//     {
//         while (true)
//         {
//             // 取任务
//             LockQueue();
//             if (IsEmpty() && _is_running)
//             {
//                 _sleep_num++;
//                 Sleep();
//                 _sleep_num++;
//             }

//             if (IsEmpty() && !_is_running)
//             {
//                 UnlockQueue();
//                 std::cout << name << " quit " << std::endl;
//                 break;
//             }

//             T task = _task_queue.front();
//             _task_queue.pop();

//             UnlockQueue();
//             // 处理任务
//             task();
//             std::cout << name << ": " << task.result() << std::endl;
//         }
//     }

// public:
//     ThreadPool(int num = default_thread_num)
//         : _thread_num(num), _is_running(false), _threads(num), _sleep_num(0)
//     {
//         pthread_mutex_init(&_mutex, nullptr);
//         pthread_cond_init(&_cond, nullptr);
//     }

//     void Init()
//     {
//         func_t func = std::bind(&ThreadPool::HandleTask, this, std::placeholders::_1);
//         for (int i = 0; i < _thread_num; ++i)
//         {
//             std::string name = "thread-" + std::to_string(i + 1);
//             _threads.emplace_back(name, func);
//         }
//     }

//     void Start()
//     {
//         _is_running = true;
//         for (auto &thread : _threads)
//         {
//             thread.Start();
//         }
//     }

//     void Stop()
//     {
//         LockQueue();
//         _is_running = false;
//         WakeUpAll();
//         UnlockQueue();
//     }

//     ~ThreadPool()
//     {
//         pthread_mutex_destroy(&_mutex);
//         pthread_cond_destroy(&_cond);
//     }

// private:
//     std::vector<Thread> _threads;
//     std::queue<T> _task_queue;

//     bool _is_running;
//     int _thread_num;
//     int _sleep_num;

//     pthread_mutex_t _mutex;
//     pthread_cond_t _cond;
// };